/**
 * Project trac. Copyright May 28, 2012.
 */
package org.mediahouse.trac;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mediahouse.trac.http.AbstractCustomHttpServlet;
import org.mediahouse.trac.model.Deliverable;
import org.mediahouse.trac.model.DeliverableServiceFactory;
import org.mediahouse.trac.util.JSONResponseDataContainer;

/**
 * @author Tin
 * @version %I%, %G%
 * 
 */
@SuppressWarnings("serial")
public class TracResourceManager extends AbstractCustomHttpServlet {

    /**
     * {@inheritDoc}
     * 
     * @see org.mediahouse.trac.http.AbstractCustomHttpServlet#doRequest(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse,
     *      org.mediahouse.trac.http.CustomHttpServlet.HttpRequestMethodType)
     */
    @Override
    public void doRequest(final HttpServletRequest req,
            final HttpServletResponse resp,
            final HttpRequestMethodType method) throws Exception {

        switch (method) {

        /**
         * The GET case handles all HTTP GET requests to retrieve the section
         * deliverables for the requesting client.
         */
        case GET:
            resp.setContentType("application/json");
            final PrintWriter out = resp.getWriter();
            try {
                final String clientName = req.getParameter("client_name");
                out.write(new JSONResponseDataContainer(new HashMap<String, Object>() {
                    {
                        if (clientName != null) put("clientName", clientName);
                        put("sections", getSections());
                    }
                }).serialize());
                status(HttpStatus.OK, resp);
            } finally {
                out.close();
            }
            break;

        /**
         * Handles all HTTP POST requests to record a section to the system
         * datastore for the requesting client.
         */
        case POST:
            resp.setContentType("text/html");
            if (tryPutSection(req)) {
                status(HttpStatus.OK, resp);
                redirect("/trac.html", resp);
            } else {
                error(HttpStatus.BAD_REQUEST, "Sorry, that's an invalid section and can't be recorded. Did you forget to specify a field?", resp);
            }
            break;
        }
    }

    /**
     * Returns a {@code List} of POJOs (plain old Java objects), representing
     * section deliverables, that are interpretable by any JSON serializer or
     * parser that can properly translate Java's basic types (Number, String,
     * Character, Boolean, null) as either primitives or wrappers for
     * primitives, as well as the two parameterized Java structs compatable with
     * JSON data structures (Map and List/Collection), into the appropriate JSON
     * data type or structure. It is also required that the JSON serializer can
     * interpret Java's native arrays in the same way that it is expected to
     * interpret Java Lists (i.e. as a JSON array).
     * <p>
     * The interpreter must be capable of identifying the runtime type of the
     * objects contained in the returned list.
     * 
     * @return the deliverables as a JSON-interpretable list of objects
     */
    private List<Object> getSections() {
        final List<Deliverable> deliverables = DeliverableServiceFactory.getDeliverableService().getDeliverables("TYPE", "EQUALS", "SECTION");
        final List<Object> sections = new ArrayList<Object>(deliverables.size());
        for (final Deliverable deliverable : deliverables) {
            sections.add(new ArrayList<Object>(6) {
                {
                    add(deliverable.getName());
                    add(deliverable.getStatus());
                    add(deliverable.getOwner());
                    add(deliverable.getQA());
                    add(deliverable.getDueDate());
                    add(deliverable.getTextNotes());
                }
            });
        }
        return sections;
    }

    /**
     * @param req
     *            the HttpServletRequest object.
     * @return {@code true} if and only if the request to record a section was
     *         successful; {@code false} otherwise
     */
    private boolean tryPutSection(final HttpServletRequest req) {
        try {
            final String name = String.valueOf(req.getParameter("name"));
            final int status = Integer.valueOf(String.valueOf(req.getParameter("status")));
            final String textNotes = req.getParameter("text_notes");
            final Date due = new Date();
            final String qa = String.valueOf(req.getParameter("qa"));
            final String owner = String.valueOf(req.getParameter("owner"));
            DeliverableServiceFactory.getDeliverableService().newDeliverable(name, status, owner, qa, due, textNotes);
            return true;
        } catch (final Exception e) {
            return false;
        }
    }
}
